package org.dromara.system.controller.coreController;

import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.R;
import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.domain.model.SmsLoginBody;
import org.dromara.common.core.exception.user.CaptchaException;
import org.dromara.common.core.exception.user.CaptchaExpireException;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.VerifyCodeUtils;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.im.core.TxTemplate;
import org.dromara.common.redis.keys.CacheConstants;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;

import org.dromara.system.domain.SysNotice;
import org.dromara.system.domain.bo.AppUserBo;
import org.dromara.system.domain.vo.AppUserVo;
import org.dromara.system.domain.vo.UserVo;
import org.dromara.system.service.AppLoginService;
import org.dromara.system.service.IAppUserService;
import org.dromara.system.service.ISysConfigService;
import org.dromara.system.service.ISysNoticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * APP登录验证
 *
 * @author Lion Li
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/app")
public class AppLoginController extends BaseController {

    private final IAppUserService appUserService;
    private final AppLoginService appLoginService;
//    @Autowired(required = false)
//    private final SmsProperties smsProperties;
    private final ISysNoticeService sysNoticeService;
    private final ISysConfigService iSysConfigService;


    /**
     * 账号密码登录
     * 登录方法
     *
     * @param loginBody 用户信息
     * @return
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @PostMapping("login")
    public R<Map<String, Object>> login(@Valid LoginBody loginBody) {
        Map<String, Object> ajax = new HashMap<>();
        // 生成令牌
        String token = appLoginService.login(loginBody.getUsername(),
            loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid(),loginBody.getTenantId()
        );
        UserVo userVo = appUserService.queryByIdUserVo(LoginHelper.getUserId());
        createImUser(userVo);
        ajax.put(Constants.TOKEN, token);
        ajax.put(Constants.USER_INFO, userVo);
        return R.ok(ajax);
    }

    /**
     * 手机验证码登录
     * 登录方法
     *
     * @param smsLoginBody 短信登录信息
     * @return 结果
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @PostMapping("mobileLogin")
    public R<Map<String, Object>> mobileLogin(SmsLoginBody smsLoginBody) {
        Map<String, Object> ajax = new HashMap<>();
        // 生成令牌
        String token = appLoginService.login(smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode());
        UserVo userVo = appUserService.queryByIdUserVo(LoginHelper.getUserId());
        createImUser(userVo);
        //后期设置租户id
        ajax.put(Constants.TOKEN, token);
        ajax.put(Constants.USER_INFO, userVo);
        return R.ok(ajax);
    }


    /**
     * 手机验证码注册
     * 注册方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @PostMapping("register")
    public R<Map<String, Object>> register(@Valid LoginBody loginBody) {
        if (StringUtils.isBlank(loginBody.getCode())) {
            return R.fail("验证码不能为空!");
        }
        AppUserVo user = appUserService.queryByPhone(loginBody.getUsername());
        if (Objects.nonNull(user)) {
            return R.fail("手机号码已注册!");
        }
        String key = CacheConstants.LOGIN_OUT + loginBody.getUsername();
        Boolean result = RedisUtils.hasKey(key);
        if (result) {
            return R.fail("账号注销1个月后才能再次注册！");
        }

        Map<String, Object> ajax = new HashMap<>(10);
        // 生成令牌
        String token = appLoginService.login(loginBody, loginBody.getCode());
        UserVo userVo = appUserService.queryByIdUserVo(LoginHelper.getUserId());
        //后期添加租户id
      //  createImUser(userVo);
        ajax.put(Constants.TOKEN, token);
        ajax.put(Constants.USER_INFO, userVo);
        return R.ok(ajax);
    }




    /**
     * 发送短信验证码
     *
     * @param phonenumber 手机号码
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @PostMapping("sendMessage")
    public R<Object> sendMessage(
        @RequestParam(name = "phonenumber") String phonenumber,
        @RequestParam(name = "type", defaultValue = "0") Integer type,
        @RequestParam(name = "otherType", defaultValue = "wechat") String otherType
    ) {
        String regex = "^1\\d{10}$";
        if (!Pattern.matches(regex, phonenumber)) {
            return R.fail("手机号码格式错误!");
        }
        if (Constants.FORGET.equals(type)) {
            AppUserVo userVo = appUserService.queryByPhone(phonenumber);
            if (Objects.isNull(userVo)) {
                return R.fail("账号未注册!");
            }
        }
        String key = CacheConstants.CAPTCHA_CODE_KEY + phonenumber;
        String sendCode = RedisUtils.getCacheObject(key);
        if (StringUtils.isNotBlank(sendCode)) {
            return R.fail("验证码已发送，请稍后在再试");
        }
        String code = VerifyCodeUtils.generateVerifyNumberCode(4);
        HashMap<String, Object> data = new HashMap<>();
//        data.put("appid", smsProperties.getAccessKeyId());
//        data.put("key", smsProperties.getAccessKeySecret());
//        data.put("code", code);
//        data.put("mobile", phonenumber);
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
//        HttpEntity<HashMap<String, Object>> formEntity = new HttpEntity<>(data, headers);
//        String body = restTemplate.postForEntity(smsProperties.getEndpoint(), formEntity, String.class).getBody();
//        JSONObject jsonObject = JSONObject.parseObject(body);
//        boolean result = jsonObject.get("code").toString().equals(Constants.FAIL);
//        if (result) {
//            //缓存短信验证码
//            RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.APP_CAPTCHA_EXPIRATION));
//            log.info("手机号码[{}]的验证码是：{}", phonenumber, code);
//            return R.ok("发送短信成功");
//        } else {
//            return R.fail("发送短信失败!");
//        }
        return R.fail("发送短信失败!");
    }


    /**
     * 获取隐私协议和用户协议
     *
     * @param type 协议类型
     * @return
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @GetMapping("notice")
    public R<SysNotice> notice(Integer type) {
        return R.ok(sysNoticeService.queryByType(String.valueOf(type)));
    }



    /**
     * 忘记密码
     *
     * @param phonenumber 手机号码
     * @param password    新密码
     * @param code        验证码
     * @return
     */
    @SaIgnore
    @RepeatSubmit(interval = 2000)
    @PostMapping("password")
    public R<String> getPassword(
        @RequestParam(name = "code") String code,
        @RequestParam(name = "password") String password,
        @RequestParam(name = "phonenumber") String phonenumber
    ) {
        String regex = "^1\\d{10}$";
        if (!Pattern.matches(regex, phonenumber)) {
            return R.fail("手机号码格式错误!");
        }
        if (password.length() < 6) {
            return R.fail("密码长度最少6位!");
        }
        String key = CacheConstants.CAPTCHA_CODE_KEY + phonenumber;
        String msCode = RedisUtils.getCacheObject(key);
//        if (smsProperties.getEnabled() && StringUtils.isBlank(msCode)) {
//            throw new CaptchaExpireException();
//        }
//        if (smsProperties.getEnabled() && !msCode.equals(code)) {
//            throw new CaptchaException();
//        }
        AppUserVo user = appUserService.queryByPhone(phonenumber);
        if (Objects.isNull(user)) {
            return R.fail("手机号码错误!");
        }
        RedisUtils.deleteObject(key);
        return R.result(appUserService.updatePassword(user.getId(), password));
    }


    /**
     * APP退出登录
     *
     * @return
     */
    @PostMapping("logOut")
    public R<Object> logOut() {
        AppUserVo appUserVo = appUserService.queryById(LoginHelper.getUserId());
        if (Objects.nonNull(appUserVo)) {
            appUserService.updateOnline(appUserVo.getId());
        }
        appLoginService.logout();
        return R.ok("退出成功");
    }

    /**
     * 获取APP的下载地址
     *
     * @return
     */
    @SaIgnore
    @GetMapping("download")
    public R<HashMap<String, String>> download() {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("ios", iSysConfigService.selectConfigByKey("app.down.ios"));
        hashMap.put("android", iSysConfigService.selectConfigByKey("app.down.android"));
        hashMap.put("downloadUrl", iSysConfigService.selectConfigByKey("app.share.h5"));
        hashMap.put("phone", iSysConfigService.selectConfigByKey("app.info.phone"));
        hashMap.put("weChat", iSysConfigService.selectConfigByKey("app.info.wechat"));
        return R.ok(hashMap);
    }



    /**
     * 注销账号
     *
     * @return
     */
    @PostMapping("logOff")
    public R<Void> logOff() {
        AppUserVo userVo = appUserService.queryById(getUserId());
        if (userVo.getStatus().equals(Constants.TWO)) {
            return R.fail("账号已注销！");
        }
        String key = CacheConstants.LOGIN_OUT + userVo.getPhone();
        long time = CacheConstants.LOGIN_OUT_DAY * 86400L;
        if (appUserService.updateStatus(userVo.getId(), Constants.TWO)) {
            RedisUtils.setCacheObject(key, time, Duration.ofSeconds(time));
        }
        appLoginService.logout();
        return R.ok("注销成功");
    }


    /**
     * 创建腾讯用户信息
     *
     * @param user 用户信息
     * @return
     */
    private void createImUser(UserVo user) {
        String code = Constants.TX_USER + user.getId();
//        TxTemplate imTemplate = SpringUtils.getBean(TxTemplate.class);
//        if (StringUtils.isBlank(user.getUuid())) {
//            Boolean result = imTemplate.accountImport(code, user.getNickName(), user.getAvatar());
//            if (result) {
//                user.setUuid(code);
//                user.setUserSign(imTemplate.getUserSign(code));
//                AppUserBo userBo = new AppUserBo();
//                userBo.setId(user.getId());
//                userBo.setUuid(code);
//                appUserService.updateByBo(userBo);
//            }
//        } else {
//            user.setUserSign(imTemplate.getUserSign(code));
//        }
    }
}
